import requests
import re
import json
import time
import random
from urllib.parse import unquote, urlparse

def get_douyin_video(url):
    # 设置随机 User-Agent
    user_agents = [
        "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
    ]
    headers = {
        "User-Agent": random.choice(user_agents),
        "Cookie": "YOUR_COOKIE_HERE",  # 替换成实际 Cookie
        "Referer": "https://www.douyin.com/",
        "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
    }
    
    # 1. 获取重定向后的真实 URL
    session = requests.Session()
    session.max_redirects = 5  # 增加重定向次数限制
    
    try:
        resp = session.head(url, headers=headers, allow_redirects=True)
        real_url = resp.url
        print(f"视频真实地址: {real_url}")
    except Exception as e:
        print(f"获取真实地址失败: {e}")
        return None
    
    # 2. 提取视频 ID - 使用正则表达式更可靠
    video_id_match = re.search(r'/video/(\d+)', real_url) or re.search(r'/share/video/(\d+)', real_url)
    if video_id_match:
        video_id = video_id_match.group(1)
        print(f"视频ID: {video_id}")
    else:
        print(f"无法提取视频ID: {real_url}")
        return None
    
    # 3. 获取页面 HTML
    try:
        html = session.get(real_url, headers=headers).text
    except Exception as e:
        print(f"获取页面失败: {e}")
        return None
    
    # 4. 尝试多种方式提取视频信息
    # 方式1: 从 JSON 数据中提取
    json_patterns = [
        r'<script id="RENDER_DATA" type="application/json">(.*?)</script>',
        r'<script id="__UNIVERSAL_DATA_FOR_REHYDRATION__" type="application/json">(.*?)</script>',
        r'<script id="SSR_HYDRATED_DATA">window\._SSR_HYDRATED_DATA = (.*?)</script>'
    ]
    
    json_data = None
    
    for pattern in json_patterns:
        json_match = re.search(pattern, html)
        if json_match:
            try:
                json_str = unquote(json_match.group(1))
                json_data = json.loads(json_str)
                print("成功解析JSON数据")
                break
            except json.JSONDecodeError:
                try:
                    # 尝试移除可能的转义字符
                    json_str = json_str.replace('\\', '')
                    json_data = json.loads(json_str)
                    print("成功解析JSON数据(移除转义后)")
                    break
                except Exception as e:
                    print(f"JSON解析失败: {e}")
                    continue
    
    # 方式2: 如果JSON方式失败，尝试直接解析HTML
    video_url = None
    if json_data:
        # 尝试多种可能的JSON路径
        possible_paths = [
            json_data.get('app', {}).get('videoInfoRes', {}).get('item_list', [{}])[0].get('video', {}).get('play_addr', {}).get('url_list', []),
            json_data.get('aweme', {}).get('detail', {}).get('video', {}).get('play_addr', {}).get('url_list', []),
            json_data.get('video', {}).get('play_addr', {}).get('url_list', []),
            json_data.get('item', {}).get('video', {}).get('play_addr', {}).get('url_list', []),
        ]
        
        for path in possible_paths:
            if path and isinstance(path, list) and len(path) > 0:
                video_url = path[0].replace('playwm', 'play')
                break
    else:
        # 从HTML中直接提取视频URL
        video_match = re.search(r'"playAddr":"(https?://[^"]+)"', html)
        if video_match:
            video_url = video_match.group(1).replace('\\u002F', '/').replace('playwm', 'play')
    
    if not video_url:
        # 尝试备用提取方式
        video_match = re.search(r'<video[^>]+src="([^"]+)"', html)
        if video_match:
            video_url = video_match.group(1)
    
    if not video_url:
        print("无法提取视频URL")
        return None
    
    print(f"无水印视频地址: {video_url}")
    
    # 5. 下载视频
    try:
        video_headers = headers.copy()
        video_headers.update({
            "Accept-Encoding": "identity",
            "Range": "bytes=0-",
            "Referer": real_url,
            "Sec-Fetch-Dest": "video",
            "Sec-Fetch-Mode": "no-cors",
            "Sec-Fetch-Site": "same-site"
        })
        
        # 获取重定向后的真实视频 URL
        video_resp = session.head(video_url, headers=video_headers, allow_redirects=True)
        final_video_url = video_resp.url
        
        # 下载视频内容
        video_data = session.get(final_video_url, headers=video_headers).content
        
        # 保存文件
        filename = f"douyin_{video_id}_{int(time.time())}.mp4"
        with open(filename, "wb") as f:
            f.write(video_data)
        
        print(f"视频已保存至: {filename}")
        return filename
    except Exception as e:
        print(f"视频下载失败: {e}")
        return None

if __name__ == "__main__":
    # 示例：抖音分享短链接
    share_url = "https://v.douyin.com/ipCFL4bBgYk/"
    get_douyin_video(share_url)